﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using UtilPublic.ServerLoger;
using System.Net.Sockets;
using UnityEngine;
using gpb = global::Google.Protobuf;
using ConfClient;

namespace SvCore.Tcp
{
    public static class MySocket
    {
        public static ConcurrentQueue<MyPackage> ListMsg = new ConcurrentQueue<MyPackage>();

        private static Socket clientSocket;
        private static int BufferLen = 409600;
        private static byte[] ReadM = new byte[409600];
        private static int recvoffest = 0;

        public static bool SocketStart()
        {
            try
            {
                //实例化socket
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //连接服务器
                clientSocket.Connect("127.0.0.1", 8888);

                clientSocket.BeginReceive(ReadM, recvoffest, BufferLen - recvoffest, SocketFlags.None, new AsyncCallback(ReceiveCallBack), ReadM);

                loger.Debug($"链接到服务器: ");

                return clientSocket.Connected;
            }
            catch (Exception ex)
            {
                loger.Debug("服务器异常:" + ex.Message);
                return false;
            }
        }
        public static bool Connected => clientSocket?.Connected ?? false;
        private static void ReceiveCallBack(IAsyncResult ar)
        {
            int readCount = 0;

            try
            {
                //读取消息长度
                readCount = clientSocket.EndReceive(ar);//调用这个函数来结束本次接收并返回接收到的数据长度。
                recvoffest += readCount;
                if (recvoffest > BufferLen)
                {
                    loger.Debug($"出现Socket异常");
                    return;
                }

                if (readCount <= 0)
                {
                    recvoffest = 0;
                    loger.Debug($"出现Socket异常 readCount <= 0");
                    //disconnect();
                    return;
                }

                DeCodePacket(ref ReadM, ref recvoffest);
            }
            catch (Exception ex)//出现Socket异常就关闭连接
            {
                recvoffest = 0;
                loger.Debug($"出现Socket异常 {ex.Message}");
                return;
            }
            clientSocket.BeginReceive(ReadM, recvoffest, BufferLen - recvoffest, SocketFlags.None, new AsyncCallback(ReceiveCallBack), ReadM);
        }
        private static int DeCodePacket(ref byte[] buf, ref int recvOffest)
        {
            //Info($"DeCodePacket:  buf:{BitConverter.ToString(buf)}");
            int decodeOffest = 0;
            int datalen = 0;
            uint pid = 0;
            ushort code = 0;
            //loger.Debug($"recvOffest {recvOffest}");
            //loger.Debug($"decodeOffest {decodeOffest}");
            while (recvOffest - decodeOffest >= 10)
            {
                datalen = BitConverter.ToInt32(buf, decodeOffest);
                pid = BitConverter.ToUInt32(buf, decodeOffest + 4);
                code = BitConverter.ToUInt16(buf, decodeOffest + 8);

                //loger.Debug($"datalen {datalen}");
                //loger.Debug($"pid {pid}");
                //loger.Debug($"code {code}");

                if (datalen > recvOffest - (decodeOffest + 4))
                {
                    //continue recv packet
                    break;
                }

                decodeOffest += 10;
                byte[] buffer = new byte[datalen - 2 - 4];
                Buffer.BlockCopy(buf, decodeOffest, buffer, 0, datalen - 2 - 4);
                decodeOffest += datalen - 2 - 4;

                MsgReceive(datalen, pid, code, buffer);
            }

            if (decodeOffest > 0 && decodeOffest < recvOffest)
            {
                Buffer.BlockCopy(buf, decodeOffest, buf, 0, recvOffest - decodeOffest);
            }

            recvOffest = recvOffest - decodeOffest;

            return 1;
        }

        private static void MsgReceive(int datalen, uint pid, ushort code, byte[] buffer)
        {
            //var str = Encoding.Default.GetString(buffer);
            //Info("接收到服务器数据: " + str);
            //Info("接收到服务器数据: " + BitConverter.ToString(buffer));

            //App.Info($"接收到服务器数据:  datalen:{datalen} pid:{pid} buffer:{BitConverter.ToString(buffer)}");
            //MsgHandle((EPid)pid, buffer);

            //loger.Debug($"接收数据:  datalen:{datalen} pid:{pid} code:{(EProtocolResult)code}:{code}");
            //loger.Debug($"接收数据:  buffer:{buffer.Length} buffer:{buffer}");
            var msg = new MyPackage();
            msg.ProtocolId = pid;
            msg.Ecode = (short)code;
            msg.Body = buffer;
            ListMsg.Enqueue(msg);
        }
        //向服务器发送数据
        public static void Send<T>(T msg) where T : gpb.IMessage
        {
            var pack = MyPackage.From(msg);
            SendNetPack(pack);
        }
        //向服务器发送协议ID
        public static void SendNetPack(MyPackage pack)
        {
            try
            {
                //创建NetWorkStream
                NetworkStream ns;
                //加锁，避免在多线程下出问题
                lock (clientSocket)
                {
                    ns = new NetworkStream(clientSocket);
                }
                var data = pack.Encode();
                ns.BeginWrite(data, 0, data.Length, new AsyncCallback(SendCallBack), ns);
                //App.Debug($"发送消息:  datalen:{pack.Data.Length} pid:{(EPid)pack.Pid}:{pack.Pid}");
            }
            catch
            {
                clientSocket.Close();
            }

        }
        public static void SendCallBack(IAsyncResult ar)
        {
            NetworkStream ns = (NetworkStream)ar.AsyncState;
            try
            {
                ns.EndWrite(ar);
                ns.Flush();
                ns.Close();
            }
            catch
            {
                clientSocket.Close();
            }
        }

    }
}
